home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 176-200 / 190 / nethack / een.zoo / wizard.c < prev    next >
C/C++ Source or Header  |  1988-07-24  |  12KB  |  519 lines

  1. /*    SCCS Id: @(#)wizard.c   2.3     88/02/11
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3.  
  4. /* wizard code - inspired by rogue code from Merlyn Leroy (digi-g!brian) */
  5. /*           - heavily modified to give the wiz balls.  (genat!mike)   */
  6.  
  7. #include "hack.h"
  8. extern struct permonst pm_wizard;
  9. extern struct monst *makemon();
  10. extern struct obj *carrying(), *mksobj_at();
  11.  
  12. /* #if defined(HARD) || defined(DGKMOD)*/
  13. #ifdef HARD
  14. # define XXX
  15. #endif
  16. #ifdef DKGMOD
  17. # define XXX
  18. #endif
  19.  
  20. #ifdef XXX
  21. # ifdef SAC
  22. char    nasties[] = "cdDeImoPTUVwxXz3&,:;";
  23. # else
  24. char    nasties[] = "cdDeImoPTUVwxXz&,:;";
  25. # endif
  26. #define WIZSHOT     2
  27. #else
  28. #define WIZSHOT     6    /* one chance in WIZSHOT that wizard will try magic */
  29. #endif
  30. #undef XXX
  31.  
  32. #define BOLT_LIM    8    /* from this distance D and 1 will try to hit you */
  33.  
  34. char wizapp[] = "@&DNPTUVXcemntx";
  35.  
  36. #ifdef DGKMOD
  37. #define URETREATING(x,y) (movedist(u.ux,u.uy,x,y) > movedist(u.ux0,u.uy0,x,y))
  38. extern char mlarge[];
  39.  
  40. movedist(x0, x1, y0, y1)
  41. {
  42.     register int absdx, absdy;
  43.  
  44.     absdx = abs(x1 - x0);
  45.     absdy = abs(y1 - y0);
  46.  
  47.     return (absdx + absdy - min(absdx, absdy));
  48. }
  49. #endif
  50.  
  51. /* If he has found the Amulet, make the wizard appear after some time */
  52. amulet(){
  53.     register struct obj *otmp;
  54.     register struct monst *mtmp;
  55.  
  56.     if(!flags.made_amulet || !flags.no_of_wizards)
  57.         return;
  58.     /* find wizard, and wake him if necessary */
  59.     for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  60.         if(mtmp->data->mlet == '1' && mtmp->msleep && !rn2(40))
  61.         for(otmp = invent; otmp; otmp = otmp->nobj)
  62.             if(otmp->olet == AMULET_SYM && !otmp->spe) {
  63.             mtmp->msleep = 0;
  64.             if(dist(mtmp->mx,mtmp->my) > 2)
  65.                 pline(
  66.     "You get the creepy feeling that somebody noticed your taking the Amulet."
  67.                 );
  68.             return;
  69.             }
  70. }
  71.  
  72. wiz_hit(mtmp)
  73. register struct monst *mtmp;
  74. {
  75.     /* if we have stolen or found the amulet, we disappear */
  76.     if(mtmp->minvent && mtmp->minvent->olet == AMULET_SYM &&
  77.         mtmp->minvent->spe == 0) {
  78.         /* vanish -- very primitive */
  79.         fall_down(mtmp);
  80.         return(1);
  81.     }
  82.  
  83.     /* if it is lying around someplace, we teleport to it */
  84.     if(!carrying(AMULET_SYM)) {
  85.         register struct obj *otmp;
  86.  
  87.         for(otmp = fobj; otmp; otmp = otmp->nobj)
  88.         if(otmp->olet == AMULET_SYM && !otmp->spe) {
  89.             if((u.ux != otmp->ox || u.uy != otmp->oy) &&
  90.                !m_at(otmp->ox, otmp->oy)) {
  91.  
  92.             /* teleport to it and pick it up */
  93.             mtmp->mx = otmp->ox;
  94.             mtmp->my = otmp->oy;
  95.             freeobj(otmp);
  96.             mpickobj(mtmp, otmp);
  97.             pmon(mtmp);
  98.             return(0);
  99.             }
  100.             goto hithim;
  101.         }
  102.         return(0);                          /* we don't know where it is */
  103.     }
  104. hithim:
  105.     if(rn2(2)) {                            /* hit - perhaps steal */
  106.  
  107.         /* if hit 1/20 chance of stealing amulet & vanish
  108.         - amulet is on level 26 again. */
  109.         if(hitu(mtmp, d(mtmp->data->damn,mtmp->data->damd))
  110.         && !rn2(20) && stealamulet(mtmp))
  111.         ;
  112.     }
  113.     else    inrange(mtmp);                  /* try magic */
  114.     return(0);
  115. }
  116.  
  117. #ifdef DGKMOD
  118. /* Check if a monster is carrying a particular item.
  119.  */
  120. struct obj *
  121. m_carrying(mtmp, type)
  122. struct monst *mtmp;
  123. int type;
  124. {
  125.     register struct obj *otmp;
  126.  
  127.     for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
  128.         if(otmp->otyp == type)
  129.             return(otmp);
  130.     return((struct obj *) 0);
  131. }
  132.  
  133. /* Remove an item from the monster's inventory.
  134.  */
  135. m_useup(mon, obj)
  136. struct monst *mon;
  137. struct obj *obj;
  138. {
  139.     struct obj *otmp, *prev;
  140.  
  141.     prev = ((struct obj *) 0);
  142.     for (otmp = mon->minvent; otmp; otmp = otmp->nobj) {
  143.         if (otmp == obj) {
  144.             if (prev)
  145.                 prev->nobj = obj->nobj;
  146.             else
  147.                 mon->minvent = obj->nobj;
  148.             free((char *) obj);
  149.             break;
  150.         }
  151.         prev = otmp;
  152.     }
  153. }
  154.  
  155. m_throw(x, y, dx, dy, range, obj)
  156. register int x,y,dx,dy,range;        /* direction and range */
  157. register struct obj *obj;
  158. {
  159.     register struct monst *mtmp;
  160.     struct objclass *oclass = &objects[obj->otyp];
  161.     char sym = obj->olet;
  162.     int damage;
  163.     extern char *exclam();
  164.  
  165.     bhitpos.x = x;
  166.     bhitpos.y = y;
  167.  
  168.     if(sym) tmp_at(-1, sym);        /* open call */
  169.     while(range-- > 0) {
  170.         bhitpos.x += dx;
  171.         bhitpos.y += dy;
  172.         if(mtmp = m_at(bhitpos.x,bhitpos.y)) {
  173.             damage = index(mlarge, mtmp->data->mlet)
  174.                 ? oclass->wldam
  175.                 : oclass->wsdam;
  176. #ifdef KAA
  177. # ifdef KOPS
  178.             if(obj->otyp == CREAM_PIE) damage = 0;
  179. # endif
  180.             if(mtmp->data->ac + 8 <= rnd(20))
  181.                 miss(oclass->oc_name, mtmp);
  182.             else {
  183. #endif /* KAA */
  184.                 hit(oclass->oc_name, mtmp, exclam(damage));
  185.                 mtmp->mhp -= damage;
  186.                 if(mtmp->mhp < 1) {
  187.                     pline("%s is killed!", (Blind) ? "It" : Monnam(mtmp));
  188.                     mondied(mtmp);
  189.                 }
  190.                 range = 0;
  191. #ifdef KAA
  192. # ifdef KOPS
  193.                 if(obj->otyp == CREAM_PIE) {
  194.  
  195.                     pline("%s is blinded by the pie.", (Blind) ? "It" : Monnam(mtmp));
  196.                     if(mtmp->msleep) mtmp->msleep = 0;
  197.                     setmangry(mtmp);
  198.                     mtmp->mcansee = 0;
  199.                     mtmp->mblinded += rnd(25);
  200.                     if (mtmp->mblinded <= 0)
  201.                         mtmp->mblinded = 127;
  202.                 } else
  203. # endif /* KOPS */
  204.                     if(obj->otyp == ENORMOUS_ROCK) {
  205.                     mksobj_at(ENORMOUS_ROCK, bhitpos.x, bhitpos.y);
  206.                     fobj->quan=1;
  207.                     stackobj(fobj);
  208.                 }
  209.             }
  210. #endif /* KAA */
  211.         }
  212.         if (bhitpos.x == u.ux && bhitpos.y == u.uy) {
  213.             if (multi)
  214.                 nomul(0);
  215. #ifdef KAA
  216. /* For giants throwing rocks, the rock which hits you shouldn't disappear. */
  217. # ifdef KOPS
  218. /* Cream pies must disappear if they hit or miss. */
  219.             { int hit, blindinc, thitu();
  220.              if (!(hit = thitu(8, (obj->otyp != CREAM_PIE) ?
  221.                 rnd(oclass->wldam) : 0, oclass->oc_name))
  222.                 && obj->otyp != CREAM_PIE
  223. # else
  224.              if (!thitu(8, rnd(oclass->wldam), oclass->oc_name)
  225. # endif /* KOPS /**/
  226.                 || obj->otyp == ENORMOUS_ROCK) {
  227. #else
  228.              if (!thitu(8, rnd(oclass->wldam), oclass->oc_name)) {
  229. #endif /* KAA /**/
  230.                 mksobj_at(obj->otyp, u.ux, u.uy);
  231.                 fobj->quan = 1;
  232.                 stackobj(fobj);
  233.              }
  234. /* #if defined(KAA) && defined(KOPS) */
  235. #ifdef KAA
  236. # ifdef KOPS
  237.              if(hit && obj->otyp == CREAM_PIE) {
  238.                 if(!Blind)  pline("Yeech! You've been creamed.");
  239.                 else    pline("There's something sticky all over your face.");
  240.                 /* blindfold keeps pie filling out of your eyes */
  241.                 if (!Blindfolded) {
  242.                 u.ucreamed += (blindinc = rnd(25));
  243.                 Blinded += blindinc;
  244.                 seeoff(0);
  245.                 }
  246.              }
  247.             }
  248. # endif
  249. #endif
  250.             range = 0;
  251.         }
  252.         tmp_at(bhitpos.x, bhitpos.y);
  253. #ifdef SINKS
  254.         if(IS_SINK(RM_TYP(levl[bhitpos.x][bhitpos.y])))
  255.             break;    /* thrown objects fall on sink */
  256. #endif
  257.     }
  258.     tmp_at(-1, -1);
  259. }
  260. #endif
  261.  
  262. /* Return 1 if it's OK for the monster to move as well as (throw,
  263.  * zap, etc).
  264.  */
  265. inrange(mtmp)
  266. register struct monst *mtmp;
  267. {
  268.     register schar tx,ty;
  269. #ifdef DGKMOD
  270.     struct obj *otmp;
  271.     register xchar x, y;
  272. #endif
  273.     /* do nothing if cancelled (but make '1' say something) */
  274.     if(mtmp->data->mlet != '1' && mtmp->mcan) return(1);
  275.  
  276.     /* spit fire only when both in a room or both in a corridor */
  277. #ifndef RPH
  278.     if(inroom(u.ux,u.uy) != inroom(mtmp->mx,mtmp->my)) return(1);
  279. #endif
  280.     tx = u.ux - mtmp->mx;
  281.     ty = u.uy - mtmp->my;
  282. #ifdef DGKMOD
  283.     if ((!tx || !ty || abs(tx) == abs(ty))  /* straight line or diagonal */
  284.         && movedist(tx, 0,  ty, 0) < BOLT_LIM) {
  285.         /* Check if there are any dead squares between.  If so,
  286.          * it won't be possible to shoot.
  287.          */
  288.         for (x = mtmp->mx, y = mtmp->my; x != u.ux || y != u.uy;
  289.                 x += sgn(tx), y += sgn(ty))
  290.             if (!ACCESSIBLE(RM_TYP(levl[x][y])))
  291.                 return(1);
  292.  
  293.         switch(mtmp->data->mlet) {
  294. #ifdef KOPS
  295.         case 'O':
  296. #endif
  297. #ifdef KAA
  298.         case '9':
  299. #endif
  300.         case 'K':
  301.         case 'C':
  302.         /* If you're coming toward the monster, the monster
  303.          * should try to soften you up with arrows.  If you're
  304.          * going away, you are probably hurt or running.  Give
  305.          * chase, but if you're getting too far away, throw.
  306.          */
  307.         x = mtmp->mx;
  308.         y = mtmp->my;
  309. #ifdef KOPS
  310.         otmp = (mtmp->data->mlet == 'O') ? m_carrying(mtmp, DART)
  311. # ifdef KAA
  312.                : (mtmp->data->mlet == 'K') ? m_carrying(mtmp, CREAM_PIE)
  313. # endif
  314. #else
  315.         otmp = (mtmp->data->mlet == 'K') ? m_carrying(mtmp, DART)
  316. #endif
  317. #ifdef KAA
  318.             : (mtmp->data->mlet == '9') ? m_carrying(mtmp, ENORMOUS_ROCK)
  319. #endif
  320.             : m_carrying(mtmp, CROSSBOW_BOLT);
  321.         if (otmp && (!URETREATING(x,y)
  322.             || !rn2(BOLT_LIM - movedist(x, u.ux, y, u.uy)))) {
  323.                 m_throw(mtmp->mx, mtmp->my, sgn(tx), sgn(ty),
  324.                     BOLT_LIM, otmp);
  325.                 if (!--otmp->quan )
  326.                     m_useup(mtmp, otmp);
  327.                 return(0);
  328.             }
  329.         break;
  330. #else
  331.     if((!tx && abs(ty) < BOLT_LIM) || (!ty && abs(tx) < BOLT_LIM)
  332.         || (abs(tx) == abs(ty) && abs(tx) < BOLT_LIM)){
  333.         switch(mtmp->mappearance) {
  334. #endif
  335.         case 'D':
  336.         /* spit fire in the direction of @ (not nec. hitting) */
  337.         buzz((int) - 10 - (mtmp->dragon),
  338.             mtmp->mx,mtmp->my,sgn(tx),sgn(ty));
  339.         break;
  340. #ifdef HARD
  341.         case '&':
  342.         demon_hit(mtmp);
  343.         break;
  344. #endif
  345.         case '1':
  346.         if(rn2(WIZSHOT)) break;
  347.         /* if you zapped wizard with wand of cancellation,
  348.         he has to shake off the effects before he can throw
  349.         spells successfully.  Sometimes they fail anyway */
  350.         if(mtmp->mcan ||
  351. #ifdef HARD
  352.            !rn2(10)
  353. #else
  354.            !rn2(2)
  355. #endif
  356.            ) {
  357.             if(canseemon(mtmp))
  358.                 pline("%s makes a gesture, then curses.",
  359.                     Monnam(mtmp));
  360.             else    pline("You hear mumbled cursing.");
  361.  
  362.             if(!rn2(3)) {
  363.             mtmp->mspeed = 0;
  364.             mtmp->minvis = 0;
  365.             }
  366.             if(!rn2(3)) mtmp->mcan = 0;
  367.  
  368.         } else {
  369.             if(canseemon(mtmp)){
  370.             if(!rn2(6) && !Invis) {
  371.                 pline("%s hypnotizes you.", Monnam(mtmp));
  372.                 nomul(-rn2(3) + 3); /* bug fix by ab@unido */
  373.                 break;
  374.             } else
  375.                 pline("%s chants an incantation.", Monnam(mtmp));
  376.             } else
  377.                 pline("You hear a mumbled incantation.");
  378.             switch(rn2(Invis ? 5 : 6)) {
  379.             case 0:
  380.             /* create a nasty monster from a deep level */
  381.             nasty();
  382.             break;
  383.             case 1:
  384.             pline("\"Destroy the thief, my pets!\"");
  385. #ifdef HARD
  386.             nasty();
  387. #endif
  388.             aggravate();    /* aggravate all the monsters */
  389.             /* fall into next case */
  390.             case 2:
  391.             if (flags.no_of_wizards == 1 && !rn2(3)) {
  392.                 /* if only 1 wizard, clone himself */
  393.                 pline("Double Trouble...");
  394.                 clonewiz(mtmp);
  395.             }
  396.             break;
  397.             case 3:
  398.             if(mtmp->mspeed == MSLOW)       mtmp->mspeed = 0;
  399.             else                mtmp->mspeed = MFAST;
  400.             break;
  401.             case 4:
  402.             mtmp->minvis = 1;
  403.             break;
  404.             case 5:
  405.             /* Only if not Invisible */
  406.             pline("You hear a clap of thunder!");
  407.             /* shoot a bolt of fire or cold, or a sleep ray */
  408.             /* or death, or lightning, but not  magic missile */
  409.             buzz(-rnd(5),mtmp->mx,mtmp->my,sgn(tx),sgn(ty));
  410.             break;
  411.             }
  412.         }
  413.         }
  414.         if(u.uhp < 1) done_in_by(mtmp);
  415.     }
  416.     return(1);
  417. }
  418.  
  419. aggravate()
  420. {
  421.     register struct monst *mtmp;
  422.  
  423.     for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  424.         mtmp->msleep = 0;
  425.         if(mtmp->mfroz && !rn2(5))
  426.             mtmp->mfroz = 0;
  427.     }
  428. }
  429.  
  430. clonewiz(mtmp)
  431. register struct monst *mtmp;
  432. {
  433.     register struct monst *mtmp2;
  434.  
  435.     if(mtmp2 = makemon(PM_WIZARD, u.ux, u.uy)) {
  436.         flags.no_of_wizards = 2;
  437.         mtmp2->mtame = mtmp2->mpeaceful = 0;
  438.         unpmon(mtmp2);
  439.         mtmp2->mappearance = wizapp[rn2(sizeof(wizapp)-1)];
  440.         pmon(mtmp2);
  441.     }
  442. }
  443.  
  444. nasty() {
  445.  
  446. #ifdef HARD
  447.     register struct monst    *mtmp;
  448.     struct monst    *mkmon_at();
  449.     register int    i, nastynum, tmp;
  450.  
  451.     nastynum = sizeof(nasties) - 1;
  452.     tmp = (u.ulevel > 3) ? u.ulevel/3 : 1;  /* just in case -- rph */
  453.  
  454.     for(i = rnd(tmp); i > 0; --i)
  455.         if((mtmp = mkmon_at(nasties[rn2(nastynum)], u.ux, u.uy)))  {
  456.  
  457.         mtmp->msleep = 0;
  458.         mtmp->mpeaceful = 0;
  459.         }
  460. #else
  461.     (void) makemon((struct permonst *)0, u.ux, u.uy);
  462. #endif
  463.     return(0);
  464. }
  465.  
  466. #ifdef HARD
  467. /*    Here, we make trouble for the poor shmuck who actually    */
  468. /*    managed to do in the Wizard.                */
  469. intervene() {
  470.  
  471.     switch(rn2(6)) {
  472.  
  473.         case 0:
  474.         case 1:    pline("You feel vaguely nervous.");
  475.             break;
  476.         case 2:    pline("You notice a black glow surrounding you.");
  477.             rndcurse();
  478.             break;
  479.         case 3:    aggravate();
  480.             break;
  481.         case 4:    nasty();
  482.             break;
  483.         case 5:    resurrect();
  484.             break;
  485.     }
  486. }
  487.  
  488. wizdead(mtmp)
  489. register struct monst    *mtmp;
  490. {
  491.     flags.no_of_wizards--;
  492.     if(! u.udemigod)  {
  493.  
  494.         u.udemigod = TRUE;
  495.         u.udg_cnt = rn1(250, 50);
  496.  
  497.     /*  Make the wizard meaner the next time he appears  */
  498.         mtmp->data->mlevel++;
  499.         mtmp->data->ac--;
  500.     } else
  501.         mtmp->data->mlevel++;
  502. }
  503.  
  504.  
  505. /*    Let's resurrect the wizard, for some unexpected fun.    */
  506. resurrect() {
  507. register struct monst    *mtmp;
  508.  
  509.         if(mtmp = makemon(PM_WIZARD, u.ux, u.uy)) {
  510.  
  511.         mtmp->msleep = mtmp->mtame = mtmp->mpeaceful = 0;
  512.         flags.no_of_wizards++;
  513.         pline("A voice booms out...");
  514.         pline("\"So you thought you could kill me, fool.\"");
  515.         }
  516.  
  517. }
  518. #endif /* HARD /**/
  519.